/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.osdtsystem.functions;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.osdtsystem.graphs.GraphAccessor;

/**
 *
 * @author matthias
 */
public class FuncLogSumExp extends AbstractSingletonFunction<Double> {
    List<Function<? extends Number>> numbers;
    
    FuncLogSumExp(Function<? extends Number>... numbers) {
        this.numbers = Arrays.asList(numbers);
    }

    @Override
    public Double _singletonFunctionValue(LocalFunction<?, ?> caller, FunctionContext context,
            GraphAccessor accessor) {
        // Find list of numbers and sort them
        List<Double> values = new ArrayList<Double>();
        for (Function<? extends Number> f : numbers) {
            for (Number number : f.functionValue(caller, context, accessor)) {
                values.add(number.doubleValue());
            }
        }
        Collections.sort(values);

        // Return NaN if no values are computed
        if (values.size() == 0)
            return Double.NaN;

        // Find largest value and compute sum
        double max = values.get(values.size()-1);
        double expsum = 0;
        for (Double value : values) {
            expsum += Math.exp(value-max);
        }
        return max + Math.log(expsum);
    }

    @Override
    void toStringBuilder(FunctionStringBuilder builder) {
        builder.addSubfunctions(numbers);
    }
}
